home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C++ / Applications / Quotes 1.0 / src / main.cp < prev    next >
Encoding:
Text File  |  1995-12-17  |  24.9 KB  |  1,071 lines  |  [TEXT/KAHL]

  1. #include "interface.h"
  2. #include "window.h"
  3. #include "menus.h"
  4. #include "main.h"
  5.  
  6. #include <limits.h>
  7.  
  8. extern short nCurrentFont; // from menus.cp
  9. extern short nDefaultFont; // from menus.cp
  10. extern short nCurrentSize; // from menus.cp
  11. extern short nDefaultSize; // from menus.cp
  12. extern short nCurrentVoice; // from menus.cp
  13. extern short nDefaultVoice; // from menus.cp
  14. extern short cVoices; // from menus.cp
  15. extern short *pVoices; // from menus.cp
  16.  
  17. // will become part of the application object
  18. int fContinue = 1;
  19. RgnHandle hrgnMouse = NULL;
  20. short fForeground;
  21. SpeechChannel chan = NULL;
  22. Ptr pSpoken = NULL;
  23. DialogPtr pdlgAbout = NULL;
  24. DialogPtr pdlgGoto = NULL;
  25. short fScrapChanged;
  26.  
  27. short selUndoAction;
  28. short selUndo;
  29. WindowPtr pwinUndo; // active window
  30. short mnFontUndo, mnFontRedo; // menu item numbers
  31. short mnSizeUndo, mnSizeRedo;
  32. short mnVoiceUndo, mnVoiceRedo;
  33. int nQuoteUndo, nQuoteRedo; // quote numbers for the document pwinUndo
  34.  
  35. void LocalToGlobalRect(Rect *pr) {
  36.     Point pt;
  37.     pt.v = pr->top;
  38.     pt.h = pr->left;
  39.     LocalToGlobal(&pt);
  40.     pr->top = pt.v;
  41.     pr->left = pt.h;
  42.     pt.v = pr->bottom;
  43.     pt.h = pr->right;
  44.     LocalToGlobal(&pt);
  45.     pr->bottom = pt.v;
  46.     pr->right = pt.h;
  47. } // LocalToGlobalRect
  48.  
  49. void SetMouseRegion(void) {
  50.     SetPort(pdlgGoto);
  51.     if (hrgnMouse) {
  52.         DisposeRgn(hrgnMouse);
  53.         hrgnMouse = NULL;
  54.     }
  55.     short item;
  56.     Rect r;
  57.     Handle hText;
  58.     GetDialogItem(pdlgGoto, 3, &item, &hText, &r);
  59.     Point ptMouse;
  60.     GetMouse(&ptMouse);
  61.     short fInText = PtInRect(ptMouse, &r);
  62.     RgnHandle hrgnText = NewRgn();
  63.     LocalToGlobalRect(&r);
  64.     SetRectRgn(hrgnText, r.left, r.top, r.right, r.bottom);
  65.     if (fInText) {
  66.         hrgnMouse = hrgnText;
  67.         CursHandle hcursor = GetCursor(iBeamCursor);
  68.         if (hcursor) {
  69.             HLock((Handle)hcursor);
  70.             SetCursor(*hcursor);
  71.             HUnlock((Handle)hcursor);
  72.         }
  73.     } else {
  74.         RgnHandle hrgnScreens = NewRgn();
  75.         SetRectRgn(hrgnScreens, -32768, -32768, 32766, 32766);
  76.         hrgnMouse = NewRgn();
  77.         DiffRgn(hrgnScreens, hrgnText, hrgnMouse);
  78.         DisposeRgn(hrgnScreens);
  79.         DisposeRgn(hrgnText);
  80.         InitCursor();
  81.     }
  82. } // SetMouseRegion
  83.  
  84. void Resume(void) {
  85.     ExitToShell();
  86. } // Resume
  87.  
  88. void EnableUndo(void) {
  89.     MenuHandle hmenuEdit = GetMenuHandle(MENU_EDIT);
  90.     if (!((**hmenuEdit).enableFlags & 1)) {
  91.         EnableItem(hmenuEdit, 0);
  92.         DrawMenuBar();
  93.     }
  94. } // EnableUndo
  95.  
  96. void StopSpeaking(void) {
  97.     if (chan) {
  98.         (void) DisposeSpeechChannel(chan);
  99.         chan = NULL;
  100.         DisposePtr(pSpoken);
  101.         pSpoken = NULL;
  102.     }
  103. } // StopSpeaking
  104.  
  105. void InitToolbox() {
  106.     InitGraf((Ptr) &qd.thePort); // sets qd.randSeed to 1
  107.     GetDateTime((unsigned long *)&qd.randSeed);
  108.     InitFonts();
  109.     InitWindows();
  110.     InitMenus();
  111.     TEInit();
  112.     long response;
  113.     OSErr err = Gestalt(gestaltSystemVersion, &response);
  114.     int fSystem7;
  115.     if (err == noErr)
  116.         fSystem7 = ( 0x0000FFFF & response ) > 0x0700;
  117.     else
  118.         fSystem7 = 0;
  119.     if (fSystem7) // System 7 or later, see Inside Macintosh: Macintosh TB Essentials, page 6-104
  120.         InitDialogs(NULL);
  121.     else
  122.         InitDialogs(Resume);
  123.     FlushEvents(everyEvent,0);
  124.     InitCursor();
  125. } // InitToolbox
  126.  
  127. void SetOpenDialogPoint(Point *pPt) {
  128.     Rect r = qd.screenBits.bounds;
  129.     int left = (r.right - r.left - 344) / 2; // 344 is the width of the open dialog
  130.     int top = (r.bottom - r.top - GetMBarHeight() - 166) / 4 + GetMBarHeight(); // 166 is the hight of the open dialog
  131.     SetPt(pPt, left, top);
  132. } // SetOpenDialogPoint
  133.  
  134. // the top left corner of the dialog is at 0,0
  135. void CenterDialog(DialogPtr pdlg) {
  136.     Rect r = qd.screenBits.bounds;
  137.     WindowPtr pwin = GetDialogWindow(pdlg);
  138.     CGrafPtr pPort = GetWindowPort(pwin);
  139.     Rect rdlg = pPort->portRect;
  140.     int left = (r.right - rdlg.right) / 2;
  141.     int top = (r.bottom - GetMBarHeight() - rdlg.bottom) / 4 + GetMBarHeight();
  142.     MoveWindow(pdlg, left, top, 1);
  143. } // CenterDialog
  144.  
  145. // the top left corner of the dialog is at 0,0
  146. void CenterWindow(WindowPtr pwin) {
  147.     Rect r = qd.screenBits.bounds;
  148.     CGrafPtr pPort = GetWindowPort(pwin);
  149.     Rect rdlg = pPort->portRect;
  150.     int left = (r.right - rdlg.right) / 2;
  151.     int top = (r.bottom - GetMBarHeight() - rdlg.bottom) / 4 + GetMBarHeight();
  152.     MoveWindow(pwin, left, top, 1);
  153. } // CenterWindow
  154.  
  155. void StaggerWindow(WindowPtr pwin) {
  156.     WindowPtr pwinFront = FrontWindow();
  157.     Point pt;
  158.     if (pwinFront) {
  159.         CGrafPtr pPort = GetWindowPort(pwinFront);
  160.         Rect r = pPort->portRect;
  161.         pt.h = r.left;
  162.         pt.v = r.top;
  163.         SetPort(pwinFront);
  164.         LocalToGlobal(&pt);
  165.         pt.h += 16;
  166.         pt.v += 16;
  167.         Rect rScreen = qd.screenBits.bounds;
  168.         if (pt.h+r.right > rScreen.right)
  169.             pt.h -= pt.h+r.right - rScreen.right;
  170.         if (pt.v+r.bottom > rScreen.bottom)
  171.             pt.v -= pt.v+r.bottom - rScreen.bottom;
  172.     } else {
  173.         pt.h = 4;
  174.         pt.v = 23 + GetMBarHeight();
  175.     }
  176.     MoveWindow (pwin, pt.h, pt.v, 1);
  177. } // StaggerWindow
  178.  
  179. void ConvertWD(short wd, unsigned char *pch, FSSpec *pfs) {
  180.     OSErr err;
  181.     short vRefNum;
  182.     long dirID;
  183.     long user;
  184.     err = GetWDInfo(wd, &vRefNum, &dirID, &user);
  185.     if (err == noErr) {
  186.         pfs->vRefNum = vRefNum;
  187.         pfs->parID = dirID;
  188.         for (int i = 0; i <= pch[0]; i++)
  189.             pfs->name[i] = pch[i];
  190.         (void) CloseWD(wd);
  191.     }
  192. }; // ConvertWD
  193.  
  194. OSErr SelectCookie(FSSpec *pfsCookie) {
  195.     OSType Types[1] = {'TEXT'};
  196.     long response;
  197.     OSErr err = Gestalt(gestaltStandardFileAttr, &response);
  198.     int fHasStandardFile;
  199.     if (err == noErr)
  200.         fHasStandardFile = response & (1<<gestaltStandardFile58);
  201.     else {
  202.         fHasStandardFile = 0;
  203.         err = noErr;
  204.     }
  205.     fHasStandardFile = 0; // test if SFGetFile short circuits in System 7.5
  206.     if (fHasStandardFile) {
  207.         StandardFileReply reply;
  208.         // does not support Finder short circuit of substituting an opened document
  209.         // which then requires use of Apple events for opening documents
  210.         StandardGetFile(NULL, 1, &Types[0], &reply);
  211.         if (reply.sfGood)
  212.             *pfsCookie = reply.sfFile;
  213.         else
  214.             err = userCanceledErr;
  215.     } else {
  216.         SFReply _reply;
  217.         Point pt;
  218.         SetOpenDialogPoint(&pt);
  219.         SFGetFile(pt, "\p", NULL, 1, &Types[0], NULL, &_reply);
  220.         if (_reply.good)
  221.             ConvertWD(_reply.vRefNum, &_reply.fName[0], pfsCookie);
  222.         else
  223.             err = userCanceledErr;
  224.     }
  225.     return err;
  226. } // SelectCookie
  227.  
  228. void Open(void) {
  229.     FSSpec fsQuotes;
  230.     OSErr err = SelectCookie(&fsQuotes);
  231.     if (err == noErr)
  232.         OpenFile(fsQuotes);
  233. } // Open
  234.  
  235. void OpenFile(FSSpec fsQuotes) {
  236.     CursHandle hcursor = GetCursor(watchCursor);
  237.     if (hcursor) {
  238.         HLock((Handle)hcursor);
  239.         SetCursor(*hcursor);
  240.         HUnlock((Handle)hcursor);
  241.     }
  242.     OSErr err;
  243.     QuotesDocument *pqd = new QuotesDocument(fsQuotes, err); // construct quotes document
  244.     if (err == noErr) {
  245.         QuotesWindow *pqw = new QuotesWindow(pqd, err); // construct quotes window
  246.         if (err == noErr) {
  247.             WindowPtr pwin = pqw->window();
  248.             SetWTitle(pwin, fsQuotes.name);
  249.             StaggerWindow(pwin);
  250.             ShowWindow(pwin);
  251.             SetPort(pwin);
  252.             nCurrentFont = nDefaultFont;
  253.             pqw->font = FontNumber(nCurrentFont);
  254.             TextFont(pqw->font);
  255.             nCurrentSize = nDefaultSize;
  256.             pqw->size = SizeNumber(nCurrentSize);
  257.             TextSize(pqw->size);
  258.             if (cVoices > 0)
  259.                 pqw->voice = pVoices[nDefaultVoice];
  260.             else
  261.                 pqw->voice = 0;
  262.             pqw->some();
  263.         } else
  264.             delete pqw;
  265.     } else
  266.         delete pqd;
  267.     InitCursor();
  268. } // OpenFile
  269.  
  270. // app parameters are not cleared are reset for subsequent opening of documents
  271. // may only be used once during application startup
  272. void OpenStartup(void) {
  273.     short message;
  274.     short count;
  275.     CountAppFiles(&message, &count);
  276.     AppFile theFile;
  277.     short iFile;
  278.     if (count) {
  279.         FSSpec fs;
  280.         if (message == appOpen)
  281.             for (iFile=1; iFile<=count; iFile++) {
  282.                 GetAppFiles(iFile, &theFile);
  283.                 ConvertWD(theFile.vRefNum, &theFile.fName[0], &fs);
  284.                 OpenFile(fs);
  285.                 ClrAppFiles(iFile);
  286.             }
  287.     } else
  288.         Open();
  289.     AdjustMenus();
  290. } // OpenStartup
  291.  
  292. int Setup(void) {
  293.     fForeground = 1;
  294.     MaxApplZone(); // needed to enable submenus in the Apple menu
  295.     InitToolbox();
  296.     nCurrentSize = 3; // 12 point
  297.     nDefaultSize = 3; // 12 point
  298.     selUndo = CANT_UNDO;
  299.     SetupMenus();
  300.     OpenStartup();
  301.     return noErr;
  302. } // Setup
  303.  
  304. void DisplayAbout(void) {
  305.     if (pdlgAbout) {
  306.         SelectWindow(pdlgAbout);
  307.         ShowWindow(pdlgAbout);
  308.     } else {
  309.         pdlgAbout = GetNewDialog(DLOG_ABOUT, NULL, (WindowPtr)-1);
  310.         if (pdlgAbout) {
  311.             SetWRefCon(pdlgAbout, DLOG_ABOUT);
  312.             CenterDialog(pdlgAbout);
  313.             ShowWindow(pdlgAbout);
  314.         }
  315.     }
  316. } // DisplayAbout
  317.  
  318. void DisplayGoto(void) {
  319.     if (pdlgGoto == NULL) {
  320.         pdlgGoto = GetNewDialog(DLOG_GOTO, NULL, (WindowPtr)-1);
  321.         if (pdlgGoto) {
  322.             SetWRefCon(pdlgGoto, DLOG_GOTO);
  323.             CenterDialog(pdlgGoto);
  324.         }
  325.     }
  326.     if (pdlgGoto) {
  327.         WindowPtr pwin = FrontWindow();
  328.         short windowKind;
  329.         while (pwin) {
  330.             windowKind = GetWindowKind(pwin);
  331.             if (windowKind == userKind)
  332.                 break;
  333.             pwin = GetNextWindow(pwin);
  334.         }
  335.         if (pwin) {
  336.             QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  337.             Str255 s;
  338.             int cQuotes = pqw->count();
  339.             NumToString(cQuotes, s);
  340.             ParamText(s, "\p", "\p", "\p");
  341.             int iQuotes = pqw->current() + 1; // index into quotes is zero-based
  342.             NumToString(iQuotes, s);
  343.             short item;
  344.             Rect r;
  345.             Handle hText;
  346.             GetDialogItem(pdlgGoto, 3, &item, &hText, &r);
  347.             SetDialogItemText(hText, s);
  348.             SelectDialogItemText(pdlgGoto, 3, 0, s[0]);
  349.             SelectWindow(pdlgGoto);
  350.             ShowWindow(pdlgGoto);
  351.             SetMouseRegion();
  352.             TEFromScrap();
  353.             fScrapChanged = 0;
  354.         }
  355.     }
  356. } // DisplayGoto
  357.  
  358. void address_copy(void) {
  359.     Handle hAddress = GetResource('STR ', ADDRESS);
  360.     if (hAddress) {
  361.         OSErr err = ZeroScrap();
  362.         if (err == noErr) {
  363.             unsigned long length = GetHandleSize(hAddress)-1;
  364.             HLock(hAddress);
  365.             err = PutScrap(length, 'TEXT', ((unsigned char *)*hAddress)+1);
  366.             HUnlock(hAddress);
  367.         }
  368.     }
  369. } // address_copy
  370.  
  371. void CmdUndo(void) {
  372.     WindowPtr pwin = FrontWindow();
  373.     short windowKind;
  374.     QuotesWindow *pqw;
  375.     if (pwin) {
  376.         windowKind = GetWindowKind(pwin);
  377.         pqw = (QuotesWindow *)GetWRefCon(pwin);
  378.     }
  379.     switch (selUndoAction) {
  380.         case UNDO_QUOTE:
  381.             if (pwin && windowKind == userKind)
  382.                 if (pwin == pwinUndo)
  383.                     if (selUndo == UNDO) {
  384.                         selUndo = REDO;
  385.                         nQuoteRedo = pqw->current();
  386.                         pqw->select(nQuoteUndo);
  387.                     } else {
  388.                         selUndo = UNDO;
  389.                         nQuoteUndo = pqw->current();
  390.                         pqw->select(nQuoteRedo);
  391.                     }
  392.             break;
  393.         case UNDO_FONT:
  394.             if (pwin == pwinUndo)
  395.                 if (selUndo == UNDO) {
  396.                     selUndo = REDO;
  397.                     mnFontRedo = nCurrentFont;
  398.                     CmdFont(mnFontUndo);
  399.                 } else {
  400.                     selUndo = UNDO;
  401.                     mnFontUndo = nCurrentFont;
  402.                     CmdFont(mnFontRedo);
  403.                 }
  404.             break;
  405.         case UNDO_SIZE:
  406.             if (pwin == pwinUndo)
  407.                 if (selUndo == UNDO) {
  408.                     selUndo = REDO;
  409.                     mnSizeRedo = nCurrentSize;
  410.                     CmdSize(mnSizeUndo);
  411.                 } else {
  412.                     selUndo = UNDO;
  413.                     mnSizeUndo = nCurrentSize;
  414.                     CmdSize(mnSizeRedo);
  415.                 }
  416.             break;
  417.         case UNDO_VOICE:
  418.             if (pwin == pwinUndo)
  419.                 if (selUndo == UNDO) {
  420.                     selUndo = REDO;
  421.                     mnVoiceRedo = nCurrentVoice;
  422.                     CmdVoice(mnVoiceUndo);
  423.                 } else {
  424.                     selUndo = UNDO;
  425.                     mnVoiceUndo = nCurrentVoice;
  426.                     CmdVoice(mnVoiceRedo);
  427.                 }
  428.             break;
  429.     }
  430. } // CmdUndo
  431.  
  432. void CmdVoice(short selItem) {
  433.     MenuHandle hmenu = GetMenuHandle(MENU_VOICES);
  434.     CheckItem(hmenu, nCurrentVoice, 0);
  435.     nCurrentVoice = selItem;
  436.     WindowPtr pwin = FrontWindow();
  437.     if (pwin) {
  438.         short windowKind = GetWindowKind(pwin);
  439.         if (windowKind < 0)
  440.             nDefaultVoice = selItem;
  441.         else {
  442.             QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  443.             pqw->voice = pVoices[selItem];
  444.         }
  445.     } else
  446.         nDefaultVoice = selItem;
  447.     CheckItem(hmenu, nCurrentVoice, 1);
  448. } // CmdVoice
  449.  
  450. void CmdFont(short selItem) {
  451.     WindowPtr pwin = FrontWindow();
  452.     short windowKind = GetWindowKind(pwin);
  453.     QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  454.     MenuHandle hmenu = GetMenuHandle(MENU_FONT);
  455.     CheckItem(hmenu, nCurrentFont, 0);
  456.     nCurrentFont = selItem;
  457.     if (pwin) {
  458.         if (windowKind == userKind) {
  459.             pqw->invalidate();
  460.             short nFont = FontNumber(nCurrentFont);
  461.             SetPort(pwin);
  462.             TextFont(nFont);
  463.         }
  464.     } else
  465.         nDefaultFont = selItem;
  466.     CheckItem(hmenu, nCurrentFont, 1);
  467. } // CmdFont
  468.  
  469. void CmdSize(short selItem) {
  470.     WindowPtr pwin = FrontWindow();
  471.     short windowKind = GetWindowKind(pwin);
  472.     QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  473.     MenuHandle hmenu = GetMenuHandle(MENU_SIZE);
  474.     CheckItem(hmenu, nCurrentSize, 0);
  475.     nCurrentSize = selItem;
  476.     if (pwin)
  477.         if (windowKind < 0)
  478.             nDefaultSize = selItem;
  479.         else {
  480.             pqw->invalidate();
  481.             short nSize = SizeNumber(nCurrentSize);
  482.             SetPort(pwin);
  483.             TextSize(nSize);
  484.         }
  485.     else
  486.         nDefaultSize = selItem;
  487.     CheckItem(hmenu, nCurrentSize, 1);
  488. } // CmdSize
  489.  
  490. void DoMenuCommand(long menuSelection) {
  491.     short selMenu = HiWord(menuSelection);
  492.     short selItem = LoWord(menuSelection);
  493.     WindowPtr pwin = FrontWindow();
  494.     QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  495.     short windowKind = GetWindowKind(pwin);
  496.     switch (selMenu) {
  497.         case MENU_APPLE:
  498.             if (selItem == APPLE_ABOUT)
  499.                 DisplayAbout();
  500.             else {
  501.                 Str255 name;
  502.                 MenuHandle hmenuApple = GetMenuHandle(selMenu);
  503.                 GetMenuItemText(hmenuApple, selItem, name);
  504.                 (void) OpenDeskAcc(name);
  505.             }
  506.             break;
  507.         case MENU_FILE:
  508.             switch (selItem) {
  509.                 case FILE_OPEN:
  510.                     Open();
  511.                     break;
  512.                 case FILE_CLOSE:
  513.                     if (pwin)
  514.                         RemoveWindow(pwin);
  515.                     break;
  516.                 case FILE_QUIT:
  517.                     Terminate();
  518.                     break;
  519.             }
  520.             break;
  521.         case MENU_EDIT:
  522.             int fSystemEdit = SystemEdit(selItem-1);
  523.             if (!fSystemEdit)
  524.                 switch (selItem) {
  525.                     case EDIT_UNDO:
  526.                         CmdUndo();
  527.                         break;
  528.                     case EDIT_CUT:
  529.                         DialogCut(pwin);
  530.                         fScrapChanged = 1;
  531.                         break;
  532.                     case EDIT_COPY:
  533.                         if (windowKind == userKind)
  534.                             pqw->copy();
  535.                         else if (windowKind == dialogKind) {
  536.                             long selDialog = GetWRefCon(pwin);
  537.                             switch (selDialog) {
  538.                                 case DLOG_ABOUT:
  539.                                     address_copy();
  540.                                     break;
  541.                                 case DLOG_GOTO:
  542.                                     DialogCopy(pwin);
  543.                                     fScrapChanged = 1;
  544.                                     break;
  545.                             }
  546.                         }
  547.                         break;
  548.                     case EDIT_PASTE:
  549.                         DialogPaste(pwin);
  550.                         break;
  551.                     case EDIT_CLEAR:
  552.                         DialogDelete(pwin);
  553.                         break;
  554.                     case EDIT_SELECT_ALL:
  555.                         short item;
  556.                         Rect r;
  557.                         Handle hText;
  558.                         GetDialogItem(pwin, 3, &item, &hText, &r);
  559.                         Str255 s;
  560.                         GetDialogItemText(hText, s);
  561.                         SelectDialogItemText(pwin, 3, 0, s[0]);
  562.                         break;
  563.                 }
  564.             break;
  565.         case MENU_QUOTES:
  566.             if (windowKind == userKind) {
  567.                 int selBefore = pqw->current();
  568.                 switch (selItem) {
  569.                     case QUOTES_FIRST:
  570.                         pqw->first();
  571.                         break;
  572.                     case QUOTES_PREVIOUS:
  573.                         pqw->previous();
  574.                         break;
  575.                     case QUOTES_NEXT:
  576.                         pqw->next();
  577.                         break;
  578.                     case QUOTES_LAST:
  579.                         pqw->last();
  580.                         break;
  581.                     case QUOTES_RANDOM:
  582.                         pqw->some();
  583.                         break;
  584.                 }
  585.                 int selAfter = pqw->current();
  586.                 if (selBefore != selAfter) {
  587.                     selUndoAction = UNDO_QUOTE;
  588.                     selUndo = UNDO;
  589.                     nQuoteUndo = selBefore;
  590.                     pwinUndo = pwin;
  591.                 }
  592.             }
  593.             if (selItem == QUOTES_GOTO)
  594.                 DisplayGoto();
  595.             break;
  596.         case MENU_SPEECH:
  597.             switch (selItem) {
  598.                 case SPEECH_SPEAK_ALL:
  599.                     pqw->speak();
  600.                     break;
  601.                 case SPEECH_STOP_SPEAKING:
  602.                     StopSpeaking();
  603.                     break;
  604.             }
  605.             break;
  606.         case MENU_VOICES:
  607.             if (nCurrentVoice != selItem) {
  608.                 selUndoAction = UNDO_VOICE;
  609.                 selUndo = UNDO;
  610.                 mnVoiceUndo = nCurrentVoice;
  611.                 pwinUndo = pwin;
  612.                 CmdVoice(selItem);
  613.             }
  614.             break;
  615.         case MENU_FONT:
  616.             if (nCurrentFont != selItem) {
  617.                 selUndoAction = UNDO_FONT;
  618.                 selUndo = UNDO;
  619.                 pwinUndo = pwin;
  620.                 mnFontUndo = nCurrentFont;
  621.                 CmdFont(selItem);
  622.                 EnableUndo();
  623.             }
  624.             break;
  625.         case MENU_SIZE:
  626.             if (nCurrentSize != selItem) {
  627.                 selUndoAction = UNDO_SIZE;
  628.                 selUndo = UNDO;
  629.                 pwinUndo = pwin;
  630.                 mnSizeUndo = nCurrentSize;
  631.                 CmdSize(selItem);
  632.                 EnableUndo();
  633.             }
  634.             break;
  635.         case MENU_WINDOW_6:
  636.             SelectUserWindow(selItem-2);
  637.             break;
  638.         case MENU_WINDOW_7:
  639.             SelectUserWindow(selItem);
  640.             break;
  641.     }
  642.     HiliteMenu(0);
  643. } // DoMenuCommand
  644.  
  645. void SelectUserWindow(int selWindow) {
  646.     WindowPtr pwin = FrontWindow();
  647.     short windowKind;
  648.     while (pwin) {
  649.         windowKind = GetWindowKind(pwin);
  650.         if (windowKind == userKind)
  651.             selWindow--;
  652.         if (selWindow == 0) {
  653.             SelectWindow(pwin);
  654.             break;
  655.         }
  656.         pwin = GetNextWindow(pwin);
  657.     }
  658. } // SelectUserWindow
  659.  
  660. void RemoveWindow(WindowPtr pwin) {
  661.     short windowKind = GetWindowKind(pwin);
  662.     if (windowKind < 0)
  663.         CloseDeskAcc(windowKind);
  664.     else if (windowKind == userKind) {
  665.         QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  666.         delete pqw;
  667.         if (pwin == pwinUndo)
  668.             selUndo = CANT_UNDO;
  669.     } else if (windowKind == dialogKind) {
  670.         long selDialog = GetWRefCon(pwin);
  671.         if (selDialog == DLOG_GOTO) {
  672.             DisposeRgn(hrgnMouse);
  673.             hrgnMouse = NULL;
  674.         }
  675.     }
  676. } // RemoveWindow
  677.  
  678. void Terminate(void) {
  679.     WindowPtr pwin = FrontWindow();
  680.     EventRecord evt;
  681.     while (pwin) {
  682.         RemoveWindow(pwin);
  683.         while (WaitNextEvent(updateMask+activMask, &evt, 0, NULL))
  684.             ProcessEvent(evt);
  685.         pwin = FrontWindow();
  686.     }
  687.     fContinue = 0;
  688. } // Terminate
  689.  
  690. void DoGrow(WindowPtr pwin, Point ptMouse) {
  691.     Rect rSize;
  692.     SetRect(&rSize, 64, 64, 32767-1, 32767-1); // subtract 1 for an old region bug, confirmed by sample code
  693.     long winSize = GrowWindow(pwin, ptMouse, &rSize);
  694.     if (winSize) {
  695.         short hSize = HiWord(winSize); // window height
  696.         short wSize = LoWord(winSize); // window width
  697.         SetPort(pwin);
  698.         SizeWindow(pwin, wSize, hSize, 1);
  699.         CGrafPtr pPort = GetWindowPort(pwin);
  700.         Rect r = pPort->portRect;
  701.         InvalRect(&r);
  702.     }
  703. } // DoGrow
  704.  
  705. void ContentClick(WindowPtr pwin, Point ptMouse) {
  706. } // ContentClick
  707.  
  708. void MouseEvent(EventRecord evt) {
  709.     WindowPtr pwinFront = FrontWindow();
  710.     short windowKind;
  711.     if (pwinFront)
  712.         windowKind = GetWindowKind(pwinFront);
  713.     Point ptMouse = evt.where;
  714.     WindowPtr pwin;
  715.     short part = FindWindow(ptMouse, &pwin);
  716.     switch (part) {
  717.         case inMenuBar:
  718.             AdjustMenus();
  719.             long menuSelection = MenuSelect(ptMouse);
  720.             DoMenuCommand(menuSelection);
  721.             break;
  722.         case inSysWindow:
  723.             if (windowKind==dialogKind)
  724.                 SysBeep(10);
  725.             else
  726.                 SystemClick(&evt, pwin);
  727.             break;
  728.         case inDrag:
  729.             if (windowKind==dialogKind && pwinFront!=pwin)
  730.                 SysBeep(10);
  731.             else {
  732.                 RgnHandle hrgn = GetGrayRgn();
  733.                 DragWindow(pwin, ptMouse, &(**hrgn).rgnBBox);
  734.                 short windowKindDrag = GetWindowKind(pwin);
  735.                 if (windowKindDrag == dialogKind) {
  736.                     long selDialog = GetWRefCon(pwin);
  737.                     if (selDialog == DLOG_GOTO)
  738.                         SetMouseRegion();
  739.                 }
  740.             }
  741.             break;
  742.         case inGoAway:
  743.             if (TrackGoAway(pwin, ptMouse))
  744.                 RemoveWindow(pwin);
  745.             break;
  746.         case inContent:
  747.             if (pwin != pwinFront)
  748.                 if (windowKind==dialogKind)
  749.                     SysBeep(10);
  750.                 else
  751.                     SelectWindow(pwin);
  752.             else
  753.                 ContentClick(pwin, ptMouse);
  754.             break;
  755.         case inZoomOut:
  756.         case inZoomIn:
  757.             int fZoom = TrackBox(pwin, ptMouse, part);
  758.             if (fZoom) {
  759.                 if (part == inZoomOut)
  760.                     ; // SetStandardState(pwin);
  761.                 SetPort(pwin); // needed because of ZoomWindow bug, confirmed by sample code
  762.                 ZoomWindow(pwin, part, 0);
  763.             }
  764.             break;
  765.         case inGrow:
  766.             DoGrow(pwin, ptMouse);
  767.             break;
  768.     }
  769. } // MouseEvent
  770.  
  771. int DiskEvent(EventRecord evt) {
  772.     int err = HiWord(evt.message);
  773.     if (err != noErr) {
  774.         DILoad();
  775.         Point pt;
  776.         SetPt(&pt, 100, 100);
  777.         int errDI = DIBadMount(pt, evt.message);
  778.         DIUnload();
  779.         return errDI;
  780.     }
  781.         return err;
  782. } // DiskEvent
  783.  
  784. void OsEvent(EventRecord evt) {
  785.     int selMessage = (evt.message & osEvtMessageMask) >> 24;
  786.     switch (selMessage) {
  787.         case suspendResumeMessage:
  788.             WindowPtr pwin = FrontWindow();
  789.             if (evt.message & resumeFlag) {
  790.                 fForeground = 1; // resume
  791.                 if (pdlgGoto && pwin == pdlgGoto) {
  792.                     SetMouseRegion();
  793.                     if (evt.message & convertClipboardFlag) {
  794.                         TEFromScrap();
  795.                         fScrapChanged = 0;
  796.                     }
  797.                 } else
  798.                     InitCursor();
  799.             } else {
  800.                 fForeground = 0; // suspend
  801.                  StopSpeaking();
  802.                  if (pdlgGoto && pwin == pdlgGoto) {
  803.                     if (fScrapChanged) {
  804.                         fScrapChanged = 0;
  805.                         OSErr err = ZeroScrap();
  806.                         if (err == noErr)
  807.                             TEToScrap();
  808.                     }
  809.                  }
  810.             }
  811.             // resume - activate the front window, suspend - deactivate the front window
  812.             if (pwin)
  813.                 ActivateEvent(pwin, fForeground);
  814.             break;
  815.         case mouseMovedMessage:
  816.             SetMouseRegion();
  817.             break;
  818.     }
  819. } // OsEvent
  820.  
  821. #define KEY_UNDO 122
  822. #define KEY_COPY 99
  823.  
  824. void KeyEvent(EventRecord evt) {
  825.     char keyChar = evt.message & charCodeMask;
  826.     char keyVirtual = (evt.message & keyCodeMask) >> 8;
  827.     int fCmdKey = evt.modifiers & cmdKey;
  828.     if (fCmdKey && (evt.what == keyDown) ) {
  829.         AdjustMenus();
  830.         long menuSelection = MenuKey(keyChar);
  831.         DoMenuCommand(menuSelection);
  832.     } else {
  833.         WindowPtr pwin = FrontWindow();
  834.         if (pwin) {
  835.             short windowKind = GetWindowKind(pwin);
  836.             if (windowKind == userKind) {
  837.                 QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  838.                 switch (keyVirtual) {
  839.                     case KEY_UNDO:
  840.                         CmdUndo();
  841.                         break;
  842.                     case KEY_COPY:
  843.                         pqw->copy();
  844.                 }
  845.             }
  846.         }
  847.     }
  848. } // KeyEvent
  849.  
  850. void ActivateEvent(WindowPtr pwin, int fActivate) {
  851.     short windowKind = GetWindowKind(pwin);
  852.     if (windowKind == userKind) {
  853.         DrawGrowIcon(pwin);
  854.         if (fActivate) {
  855.             SetPort(pwin);
  856.             CGrafPtr pPort = GetWindowPort(pwin);
  857.             Rect r = pPort->portRect;
  858.             r.top = r.bottom-15;
  859.             ValidRect(&r);
  860.             r = pPort->portRect;
  861.             r.left = r.right-15;
  862.             ValidRect(&r);
  863.         }
  864.     }
  865. } // ActivateEvent
  866.  
  867. void UpdateEvent(WindowPtr pwin) {
  868.     BeginUpdate(pwin);
  869.     short windowKind = GetWindowKind(pwin);
  870.     if (windowKind == userKind) {
  871.         QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  872.         pqw->draw();
  873.     }
  874.     EndUpdate(pwin);
  875. } // UpdateEvent
  876.  
  877. void ProcessEvent(EventRecord evt) {
  878.     WindowPtr pwin;
  879.     switch (evt.what) {
  880.         case mouseDown:
  881.             MouseEvent(evt);
  882.             break;
  883.         case mouseUp:
  884.         case keyUp:
  885.             break; // ignore these events
  886.         case keyDown:
  887.         case autoKey:
  888.             KeyEvent(evt);
  889.             break;
  890.         case diskEvt:
  891.             (void) DiskEvent(evt);
  892.             break;
  893.         case updateEvt:
  894.             pwin = (WindowPtr) evt.message;
  895.             UpdateEvent(pwin);
  896.             break;
  897.         case activateEvt:
  898.             pwin = (WindowPtr) evt.message;
  899.             int fActivate = evt.modifiers & activeFlag;
  900.             ActivateEvent(pwin, fActivate);
  901.             break;
  902.         case osEvt:
  903.             OsEvent(evt);
  904.             break;
  905.         case kHighLevelEvent:
  906.             // (void) HighLevelEvent(evt);
  907.             break;
  908.     }
  909. } // ProcessEvent
  910.  
  911. void CleanUp(void) {
  912.     ExitToShell();
  913. } // CleanUp
  914.  
  915. void Abort(void) {
  916.     ExitToShell();
  917. } // Abort
  918.  
  919. void NullEvent(EventRecord *pEvt) {
  920.     if (chan)
  921.         if (SpeechBusy() == 0)
  922.             StopSpeaking();
  923.     if (fForeground) {
  924.         WindowPtr pwin = FrontWindow();
  925.         if (pwin) {
  926.             short windowKind = GetWindowKind(pwin);
  927.             switch (windowKind) {
  928.                 case dialogKind:
  929.                     WindowPtr pdlg;
  930.                     short item;
  931.                     IsDialogEvent(pEvt);
  932.                     DialogSelect(pEvt, &pdlg, &item);
  933.                     break;
  934.                 case userKind:
  935.                     long response;
  936.                     OSErr err = Gestalt(gestaltHelpMgrAttr, &response);
  937.                     int fHasHelpMgr;
  938.                     if (err == noErr)
  939.                         fHasHelpMgr = response & (1<<gestaltHelpMgrPresent);
  940.                     else
  941.                         fHasHelpMgr = 0;
  942.                     Handle hmenus;
  943.                     if (fHasHelpMgr) {
  944.                         if (HMGetBalloons()) {
  945.                             CGrafPtr pPort = GetWindowPort(pwin);
  946.                             Rect r = pPort->portRect;
  947.                             r.bottom+=2;
  948.                             r.right+=2;
  949.                             r.top = r.bottom-16;
  950.                             r.left = r.right-16;
  951.                             SetPort(pwin);
  952.                             Point pt;
  953.                             GetMouse(&pt);
  954.                             OSErr err;
  955.                             if (PtInRect(pt, &r)) {
  956.                                 if (!HMIsBalloon()) {
  957.                                     HMMessageRecord message;
  958.                                     message.hmmHelpType = khmmStringRes;
  959.                                     message.u.hmmStringRes.hmmResID = BALLOON_STRINGS;
  960.                                     message.u.hmmStringRes.hmmIndex = STRING_SIZE_BOX;
  961.                                     Point tip;
  962.                                     tip.h = (r.left+r.right)/2;
  963.                                     tip.v = (r.top+r.bottom)/2;
  964.                                     LocalToGlobal(&tip);
  965.                                     err = HMShowBalloon(&message, tip, NULL, NULL, 0, 0, kHMRegularWindow);
  966.                                 }
  967.                             } else {
  968.                                 r = pPort->portRect;
  969.                                 if (PtInRect(pt, &r))
  970.                                     if (HMIsBalloon())
  971.                                         err = HMRemoveBalloon();
  972.                             }
  973.                         }
  974.                     }
  975.                     break;
  976.             }
  977.         }
  978.     }
  979. } // NullEvent
  980.  
  981. void DialogEvent(DialogPtr pdlg, short item) {
  982.     long selDialog = GetWRefCon(pdlg);
  983.     switch (selDialog) {
  984.         case DLOG_ABOUT:
  985.             if (item == 1)
  986.                 HideWindow(pdlg);
  987.             break;
  988.         case DLOG_GOTO:
  989.             if (item == 1) {
  990.                 short item;
  991.                 Rect r;
  992.                 Handle hText;
  993.                 GetDialogItem(pdlg, 3, &item, &hText, &r);
  994.                 Str255 s;
  995.                 GetDialogItemText(hText, s);
  996.                 long iQuote;
  997.                 StringToNum(s, &iQuote);
  998.                 WindowPtr pwin = FrontWindow();
  999.                 short windowKind;
  1000.                 while (pwin) {
  1001.                     windowKind = GetWindowKind(pwin);
  1002.                     if (windowKind == userKind)
  1003.                         break;
  1004.                     pwin = GetNextWindow(pwin);
  1005.                 }
  1006.                 if (pwin) {
  1007.                     QuotesWindow *pqw = (QuotesWindow *)GetWRefCon(pwin);
  1008.                     long cQuote = pqw->count();
  1009.                     if (iQuote>0 && iQuote<=cQuote) {
  1010.                         int selBefore = pqw->current();
  1011.                         if (selBefore != iQuote-1) {
  1012.                             selUndoAction = UNDO_QUOTE;
  1013.                             selUndo = UNDO;
  1014.                             nQuoteUndo = selBefore;
  1015.                             pwinUndo = pwin;
  1016.                             pqw->select(iQuote-1);
  1017.                         }
  1018.                         HideWindow(pdlg);
  1019.                         DisposeRgn(hrgnMouse);
  1020.                         hrgnMouse = NULL;
  1021.                         if (fScrapChanged) {
  1022.                             OSErr err = ZeroScrap();
  1023.                             if (err == noErr)
  1024.                                 TEToScrap();
  1025.                         }
  1026.                     } else {
  1027.                         SysBeep(10);
  1028.                         SelectDialogItemText(pdlg, 3, 0, s[0]);
  1029.                     }
  1030.                 }
  1031.             }
  1032.             if (item == 2)
  1033.                 HideWindow(pdlg);
  1034.                 if (fScrapChanged) {
  1035.                     OSErr err = ZeroScrap();
  1036.                     if (err == noErr)
  1037.                         TEToScrap();
  1038.                 }
  1039.             break;
  1040.     }
  1041. } // DialogEvent
  1042.  
  1043. void main(void) {
  1044.     int errSetup = Setup();
  1045.     if (errSetup == noErr) {
  1046.         EventRecord evt;
  1047.         short fEvent;
  1048.         WindowPtr pwinPrior, pwinActive;
  1049.         DialogPtr pdlg;
  1050.         short item;
  1051.         while (fContinue) {
  1052.             fEvent = WaitNextEvent(everyEvent, &evt, 1, hrgnMouse);
  1053.             if (fEvent) {
  1054.                 pwinPrior = FrontWindow();
  1055.                 if (IsDialogEvent(&evt)) {
  1056.                     if (DialogSelect(&evt, &pdlg, &item))
  1057.                         DialogEvent(pdlg, item);
  1058.                     else
  1059.                         ProcessEvent(evt);
  1060.                 } else
  1061.                     ProcessEvent(evt);
  1062.                 pwinActive = FrontWindow();
  1063.                 if (pwinPrior != pwinActive)
  1064.                     AdjustMenus();
  1065.             } else
  1066.                 NullEvent(&evt);
  1067.         }
  1068.         CleanUp();
  1069.     } else
  1070.         Abort();
  1071. } // main